package com.pokermind.operator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;


import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * AI决策导向的用户画像生成器
 * 将复杂统计数据转换为AI可直接使用的决策标签
 * 
 * @author PokerMind Team
 */
@Service
public class AIProfileGenerator {
    
    private static final Logger logger = LoggerFactory.getLogger(AIProfileGenerator.class);
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    /**
     * 生成用户的AI决策画像
     * 核心理念：从统计数据 → AI决策标签
     */
    public void generateAIProfile(Long userId) {
        logger.info("开始生成AI决策画像: userId={}", userId);
        
        try {
            // 1. 收集统计数据
            UserGameStats stats = collectUserStats(userId);
            
            if (stats.getTotalHands() < 50) {
                logger.warn("用户样本不足，跳过AI画像生成: userId={}, hands={}", userId, stats.getTotalHands());
                return;
            }
            
            // 2. 转换为AI决策标签
            AIProfileLabels labels = convertToAILabels(stats);
            
            // 3. 计算置信度
            double confidence = calculateConfidence(stats);
            
            // 4. 更新数据库
            updateAIProfile(userId, labels, confidence, stats.getTotalHands());
            
            logger.info("AI决策画像生成完成: userId={}, style={}, confidence={}", 
                       userId, labels.playingStyle, confidence);
            
        } catch (Exception e) {
            logger.error("AI画像生成失败: userId={}", userId, e);
            throw new RuntimeException("Failed to generate AI profile", e);
        }
    }
    
    /**
     * 收集用户统计数据
     */
    private UserGameStats collectUserStats(Long userId) {
        String sql = """
            SELECT 
                COUNT(*) as total_hands,
                COUNT(CASE WHEN hero_final_action != 'fold' OR hero_position IN ('SB','BB') THEN 1 END) * 100.0 / COUNT(*) as vpip_rate,
                COUNT(CASE WHEN hero_final_action LIKE '%raise%' THEN 1 END) * 100.0 / COUNT(*) as pfr_rate,
                COUNT(CASE WHEN hero_net_result > 0 THEN 1 END) * 100.0 / COUNT(*) as win_rate,
                AVG(hero_net_result) as avg_profit_per_hand,
                COUNT(CASE WHEN hero_went_to_showdown = 1 THEN 1 END) * 100.0 / COUNT(*) as showdown_rate,
                COUNT(CASE WHEN hero_final_action = 'fold' THEN 1 END) * 100.0 / COUNT(*) as fold_rate,
                STDDEV(hero_net_result) as profit_volatility
            FROM poker_hands 
            WHERE user_id = ? 
                AND started_at >= DATE_SUB(NOW(), INTERVAL 90 DAY)
                AND hero_final_action IS NOT NULL
            """;
        
        Map<String, Object> result = jdbcTemplate.queryForMap(sql, userId);
        return new UserGameStats(result);
    }
    
    /**
     * 将统计数据转换为AI决策标签
     */
    private AIProfileLabels convertToAILabels(UserGameStats stats) {
        AIProfileLabels labels = new AIProfileLabels();
        
        // 1. 打法风格分类 (AI策略核心)
        labels.playingStyle = determinePlayingStyle(stats.vpipRate, stats.pfrRate);
        
        // 2. 技能等级评估 (AI复杂度调整)
        labels.skillLevel = determineSkillLevel(stats.winRate, stats.avgProfitPerHand, stats.totalHands);
        
        // 3. 风险偏好 (AI风险决策)
        labels.riskTolerance = determineRiskTolerance(stats.profitVolatility, stats.showdownRate);
        
        // 4. 诈唬倾向 (AI诈唬对策)
        labels.bluffTendency = determineBluffTendency(stats.showdownRate, stats.pfrRate, stats.foldRate);
        
        // 5. 压力反应 (AI施压策略)
        labels.pressureResponse = determinePressureResponse(stats.foldRate, stats.pfrRate);
        
        // 6. 位置意识 (AI位置策略)
        labels.positionPlay = analyzePositionPlay(stats);
        
        // 7. 主要弱点识别 (AI攻击重点)
        labels.primaryWeakness = identifyPrimaryWeakness(stats);
        
        // 8. 主要优势识别 (AI规避重点)
        labels.primaryStrength = identifyPrimaryStrength(stats);
        
        // 9. 当前状态 (AI短期调整)
        labels.recentForm = assessRecentForm(stats);
        
        // 10. 学习适应性 (AI策略演进)
        labels.adaptationSpeed = assessAdaptationSpeed(stats);
        
        return labels;
    }
    
    /**
     * 打法风格判定 - AI策略匹配的核心标签
     */
    private String determinePlayingStyle(double vpip, double pfr) {
        if (vpip <= 25 && pfr >= 15) {
            return "tight_aggressive";   // 紧凶：AI需要尊重其下注
        } else if (vpip >= 30 && pfr >= 20) {
            return "loose_aggressive";   // 松凶：AI需要收紧范围等待价值
        } else if (vpip <= 25 && pfr <= 12) {
            return "tight_passive";      // 紧弱：AI可以积极偷盲和诈唬
        } else if (vpip >= 30 && pfr <= 15) {
            return "loose_passive";      // 松弱：AI应该薄价值下注，避免诈唬
        } else {
            return "unknown";           // 不明确：AI使用标准策略
        }
    }
    
    /**
     * 技能等级评估 - AI策略复杂度参考
     */
    private String determineSkillLevel(double winRate, double avgProfit, int totalHands) {
        if (winRate >= 60 && avgProfit > 2.0 && totalHands >= 1000) {
            return "expert";        // 专家：AI使用复杂策略，避免被反利用
        } else if (winRate >= 55 && avgProfit > 1.0) {
            return "advanced";      // 高级：AI使用标准策略，适度调整
        } else if (winRate >= 48 && avgProfit > 0) {
            return "intermediate";  // 中级：AI可以使用一些利用性策略
        } else {
            return "beginner";      // 新手：AI可以大胆利用其弱点
        }
    }
    
    /**
     * 确定风险偏好 - AI风险决策的关键
     */
    private String determineRiskTolerance(double profitVolatility, double showdownRate) {
        // 根据盈利波动性和摊牌率确定风险偏好
        if (profitVolatility > 0.8 && showdownRate < 0.4) {
            return "HIGH";  // 高风险偏好：波动大，很少摊牌
        } else if (profitVolatility < 0.3 && showdownRate > 0.6) {
            return "LOW";   // 低风险偏好：波动小，经常摊牌
        } else {
            return "MEDIUM"; // 中等风险偏好
        }
    }
    
    /**
     * 诈唬倾向判定 - AI诈唬对策的关键
     */
    private String determineBluffTendency(double showdownRate, double pfrRate, double foldRate) {
        if (showdownRate <= 15 && pfrRate >= 20) {
            return "over_bluffer";      // 过度诈唬：AI应该适当跟注
        } else if (showdownRate <= 25 && pfrRate >= 15) {
            return "frequent_bluffer";  // 频繁诈唬：AI可以轻松跟注
        } else if (showdownRate >= 35 && foldRate <= 40) {
            return "rarely_bluffs";     // 很少诈唬：AI应该在其下注时弃牌
        } else {
            return "selective_bluffer"; // 选择性诈唬：AI使用标准防守
        }
    }
    
    /**
     * 压力反应分析 - AI施压策略的核心
     */
    private String determinePressureResponse(double foldRate, double pfrRate) {
        if (foldRate >= 70) {
            return "folds_under_pressure";  // 被压就折：AI应该积极施压
        } else if (foldRate <= 40 && pfrRate <= 10) {
            return "calls_pressure";        // 被压就跟：AI应该减少诈唬
        } else if (pfrRate >= 25) {
            return "fights_back";           // 反击压力：AI需要准备好价值下注
        } else {
            return "unpredictable";         // 不可预测：AI使用平衡策略
        }
    }
    
    /**
     * 识别主要弱点 - AI攻击的重点目标
     */
    private String identifyPrimaryWeakness(UserGameStats stats) {
        // 简化的弱点识别逻辑，基于最明显的统计偏差
        if (stats.foldRate >= 75) {
            return "folds_to_3bet";      // 容易被3bet吓到
        } else if (stats.showdownRate >= 40 && stats.vpipRate >= 35) {
            return "calls_too_wide";     // 跟注范围过宽
        } else if (stats.showdownRate <= 15 && stats.pfrRate >= 25) {
            return "bluffs_too_much";    // 诈唬过度
        } else if (stats.winRate < 45) {
            return "weak_postflop";      // 翻牌后技术差
        } else {
            return null; // 没有明显弱点
        }
    }
    
    /**
     * 识别主要优势 - AI需要规避的对手强项
     */
    private String identifyPrimaryStrength(UserGameStats stats) {
        if (stats.winRate >= 60 && stats.showdownRate >= 25 && stats.showdownRate <= 35) {
            return "excellent_postflop";    // 翻牌后技术优秀
        } else if (stats.pfrRate >= 18 && stats.pfrRate <= 22 && stats.winRate >= 55) {
            return "disciplined_folding";   // 纪律性良好
        } else if (stats.showdownRate <= 20 && stats.winRate >= 55) {
            return "good_bluff_detection";  // 诈唬识别能力强
        } else {
            return null; // 没有明显优势
        }
    }
    
    /**
     * 评估近期状态 - AI短期策略调整
     */
    private String assessRecentForm(UserGameStats stats) {
        // 简化：基于最近表现评估 (这里用总体数据代替，实际应该查询最近数据)
        if (stats.winRate >= 65) {
            return "hot_streak";    // 热手：AI应该更加谨慎
        } else if (stats.winRate <= 35) {
            return "cold_streak";   // 冷手：AI可以更激进
        } else {
            return "stable";        // 稳定：AI使用标准策略
        }
    }
    
    /**
     * 评估学习适应性 - AI策略演进频率参考
     */
    private String assessAdaptationSpeed(UserGameStats stats) {
        // 简化评估：基于经验和表现稳定性
        if (stats.totalHands >= 5000 && stats.winRate >= 55) {
            return "highly_adaptive";   // 高适应：AI需要频繁调整策略
        } else if (stats.totalHands >= 1000) {
            return "slow_adapter";      // 慢适应：AI策略可以相对固定
        } else {
            return "pattern_fixed";     // 模式固定：AI可以利用其固定模式
        }
    }
    
    /**
     * 分析位置意识 - 简化版本
     */
    private String analyzePositionPlay(UserGameStats stats) {
        // 这里简化处理，实际应该分析各位置的具体表现
        if (stats.pfrRate >= 18 && stats.winRate >= 52) {
            return "position_aware";    // 有位置意识
        } else {
            return "position_weak";     // 位置意识差
        }
    }
    
    /**
     * 计算AI画像置信度
     */
    private double calculateConfidence(UserGameStats stats) {
        if (stats.totalHands >= 2000) {
            return 9.0;
        } else if (stats.totalHands >= 1000) {
            return 8.0;
        } else if (stats.totalHands >= 500) {
            return 7.0;
        } else if (stats.totalHands >= 200) {
            return 6.0;
        } else if (stats.totalHands >= 100) {
            return 5.0;
        } else {
            return 3.0;
        }
    }
    
    /**
     * 更新AI画像到数据库
     */
    private void updateAIProfile(Long userId, AIProfileLabels labels, double confidence, int sampleHands) {
        String sql = """
            UPDATE poker_users SET 
                playing_style = ?,
                skill_level = ?,
                risk_tolerance = ?,
                bluff_tendency = ?,
                pressure_response = ?,
                position_play = ?,
                primary_weakness = ?,
                primary_strength = ?,
                recent_form = ?,
                adaptation_speed = ?,
                ai_profile_confidence = ?,
                profile_sample_hands = ?,
                update_time = ?
            WHERE id = ?
            """;
        
        jdbcTemplate.update(sql,
            labels.playingStyle,
            labels.skillLevel,
            labels.riskTolerance,
            labels.bluffTendency,
            labels.pressureResponse,
            labels.positionPlay,
            labels.primaryWeakness,
            labels.primaryStrength,
            labels.recentForm,
            labels.adaptationSpeed,
            confidence,
            sampleHands,
            System.currentTimeMillis(),
            userId
        );
    }
    
    /**
     * 统计数据封装类
     */
    private static class UserGameStats {
        final int totalHands;
        final double vpipRate;
        final double pfrRate;
        final double winRate;
        final double avgProfitPerHand;
        final double showdownRate;
        final double foldRate;
        final double profitVolatility;
        
        UserGameStats(Map<String, Object> data) {
            this.totalHands = ((Number) data.get("total_hands")).intValue();
            this.vpipRate = ((BigDecimal) data.get("vpip_rate")).doubleValue();
            this.pfrRate = ((BigDecimal) data.get("pfr_rate")).doubleValue();
            this.winRate = ((BigDecimal) data.get("win_rate")).doubleValue();
            this.avgProfitPerHand = ((BigDecimal) data.get("avg_profit_per_hand")).doubleValue();
            this.showdownRate = ((BigDecimal) data.get("showdown_rate")).doubleValue();
            this.foldRate = ((BigDecimal) data.get("fold_rate")).doubleValue();
            this.profitVolatility = data.get("profit_volatility") != null ? 
                                  ((BigDecimal) data.get("profit_volatility")).doubleValue() : 0.0;
        }
        
        public int getTotalHands() { return totalHands; }
    }
    
    /**
     * AI决策标签封装类
     */
    private static class AIProfileLabels {
        String playingStyle;
        String skillLevel;
        String riskTolerance;
        String bluffTendency;
        String pressureResponse;
        String positionPlay;
        String primaryWeakness;
        String primaryStrength;
        String recentForm;
        String adaptationSpeed;
    }
}

